eval 'exec perl -wS $0 ${1+"$@"}'
 if 0;

use strict;
use warnings;
use POSIX qw(strftime);

use DBI();
use File::Basename;
use File::stat;

# Following variable is used as a general file descriptor for all the 
# output of the current tool (the log file). Actually, this file will
# contain the copy of both the stdout and stderr channel.
my $G_LOG;

my $G_SIMLOCKS_PATH="/data/samba_share/simlocks";

################################################################################
#
################################################################################
sub get_time
  {
    my $separator=shift @_;
    my @timelist = @_;

    my $now_time="";

    if (! defined $separator)
      {
	$separator=":";
      }

    if (scalar @timelist<1)
    {
	@timelist=localtime();
    }

    $now_time = strftime("%H".$separator."%M".$separator."%S",@timelist);

    return $now_time;
  }

################################################################################
#
################################################################################
sub get_date
  {
    my $separator=shift @_;
    my @timelist = @_;

    my $now_date="";

    if (! defined $separator)
      {
	$separator="/";
      }

    if (scalar @timelist<1)
    {
	@timelist=localtime();
    }

    $now_date = POSIX::strftime("%Y".$separator."%m".$separator."%d",@timelist);

    return $now_date;
  }



################################################################################
#
################################################################################
sub mylog
{
    if ($G_LOG)
    {
	print $G_LOG get_date()." ".get_time()." ".join("",@_);
    }
}

################################################################################
#
################################################################################
sub error
  {
    print STDERR get_date()." ".get_time()." [ERROR] ",@_;
    mylog "[ERROR] ", @_;
  }

################################################################################
#
################################################################################
sub warning
  {
    print STDERR get_date()." ".get_time()." [WARNING] ",@_;
    mylog("[WARNING],",@_);
  }

################################################################################
#
################################################################################
sub debug
  {
    my $h_ref_param=shift @_;

    if (exists $h_ref_param->{DEBUG})
      {
	print STDOUT get_date()." ".get_time()." [DEBUG] ",@_;
	mylog("[DEBUG] ",@_);
      }
  }

################################################################################
#
################################################################################
sub info
{
    print STDOUT get_date()." ".get_time()." [INFO] ",@_;
    mylog("[INFO] ",@_);
}


################################################################################
#
################################################################################
sub print_h_content
{
    my $h_ref_param=shift @_;

    debug $h_ref_param, "Printing Global Hash Content:\n";
    debug $h_ref_param, "######################################################\n";
    foreach my $thekey (keys %$h_ref_param)
    {
	debug $h_ref_param, $thekey." => ".$h_ref_param->{$thekey}."\n";
    }
    debug $h_ref_param, "######################################################\n";
}

################################################################################
#
################################################################################
sub db_connect
{
    my $h_ref_param=shift @_;

    my $dbh = DBI->connect("DBI:mysql:database=".$h_ref_param->{DBNAME}.";host=localhost",
                         $h_ref_param->{DBLOGIN}, $h_ref_param->{DBPASSWD},
                         {'RaiseError' => 0});

    $h_ref_param->{DB}=$dbh;

    return (defined $dbh);
}

################################################################################
#
################################################################################
sub db_disconnect
{
    my $h_ref_param=shift @_;
    $h_ref_param->{DB}->disconnect();
}


################################################################################
#
################################################################################
sub db_seed_file_already_processed

{
    my $h_ref_param=shift @_;
    my $imei = shift @_;
    
    my $sth = $h_ref_param->{DB}->prepare("SELECT COUNT(*) FROM seed where IMEI='$imei';");
    $sth->execute();
    my $ref = $sth->fetchrow_hashref();

    $sth->finish();

    return $ref->{'COUNT(*)'}!=0;
}

################################################################################
#
################################################################################
sub db_seed_insert
{
    my $h_ref_param=shift @_;

    my $ref_imei=shift @_;
    my $product = shift @_;
    my $create_date = shift @_;
    my $insert_date = "";
    my $l_ref_keys=shift @_;
       
    my $k1="";
    my $k2="";
    my $k3="";
    my $k4="";
    my $k5="";
    my $k6="";

    $k1=@$l_ref_keys[0];
    $k2=@$l_ref_keys[1];
    $k3=@$l_ref_keys[2];
    $k4=@$l_ref_keys[3];
    $k5=@$l_ref_keys[4];
    

    if ($$product eq "seed")
    {
	$k6=@$l_ref_keys[5];
    }
    
    foreach (@$l_ref_keys) {
	debug $h_ref_param, "keys: ".$_ ."\n";
    } 

    #debug $h_ref_param, "ref_imei: ".\$$ref_imei." -> ".join(",",$$ref_imei)."\n";
    debug $h_ref_param, "ref_imei: ".\$$ref_imei." -> ".$$ref_imei."\n";
    debug $h_ref_param, "l_ref_keys: ".\@$l_ref_keys." -> ".join(",",@$l_ref_keys)."\n";
    
    $insert_date=get_date("-")." ".get_time(":");
    my $res=0;

    my $sth = $h_ref_param->{DB}->prepare("INSERT INTO seed (IMEI,PRODUIT,DATREC,DATINT,K1,K3,K5,K7,K9,K11) VALUES ( '$$ref_imei', '$$product', '$create_date', '$insert_date', '$k1','$k2','$k3','$k4','$k5','$k6');");

    $res=$sth->execute();

    return $res;
}

################################################################################
#
################################################################################
sub file_move
{
    my $h_ref_param=shift @_;
    my $source_file=shift @_;
    my $dest_file=shift @_;
    my $file_type=shift @_;

    my $cmd="";
    my @output=();

    $cmd="mv -f \"$source_file\" \"$dest_file\"";
    debug $h_ref_param, "Executing in 'file_move' function:>$cmd<\n";
    @output=`$cmd`;

    if ($? != 0)
    {
	error("Failed to move $file_type to its final location. Produced operation output is:\n");
	error(@output);
	return 0;
    }

    return 1;
}

################################################################################
#
################################################################################
sub file_remove
{
    my $h_ref_param=shift @_;
    my $source_file=shift @_;

    my $cmd="";
    my @output=();

    $cmd="rm -f \"$source_file\"";
    debug $h_ref_param, "Executing in 'file_remove' command:>$cmd<\n";
    @output=`$cmd`;

    if ($? != 0)
    {
	error("Failed to remove $source_file.\n");
	error(@output);
	return 0;
    }

    return 1;
}

################################################################################
#
################################################################################
sub get_seed_file_list
{
    my $h_ref_param=shift @_;
    my $local_dir=shift @_;
    #my $file_type_lowercase=shift @_;
    #my $file_type_uppercase=shift @_;

    my @output=();

    my $cmd="";

    $cmd="find $local_dir -maxdepth 1 \\( -name \\*.seed -o -name \\*.D6 \\) -print";
    debug $h_ref_param, "Executing in 'get_seed_file_list' function:>$cmd<\n";
    @output=`$cmd`;

    if ( ($? != 0) )
    {
	error("Failed to execute >$cmd<. Produced output is:\n");
	error(@output);
	error("End of output. Skipping current file processing ...\n");
	return 0;
    }
    
    # Success !
    return @output;
}

################################################################################
#
################################################################################
sub get_seed_content
{ 
    my $h_ref_param=shift @_;
    my $inputfile=shift @_;
    my $ref_imei=shift @_;
    my $lref_keys=shift @_;

    my $fin;
    my $line="";
    my $imei_file="";
    my $suffix=shift @_;
    my $suffix_file="";
    my $key_counter=0;

    $$ref_imei="";
    @$lref_keys=();
    $$suffix="";

    if (($inputfile!~/(\d{15})\.([Ss][Ee][Ee][Dd])$/) && ($inputfile!~/(\d{15})\.([D][6])$/))
    {
	return 0;
    }

    $imei_file=$1;
    $suffix_file=$2;

    if (!open($fin, "<$inputfile"))
    {
	return 0;
    }
        
    while($line=<$fin>)
    {
	$line=~s/\r\n$//;
	$line=~s/\n\r$//;
	$line=~s/\n$//;
	$line=~s/\r$//;
	
	debug $h_ref_param, "SEED file content is $line \n";

	if ($line!~s/^(\d{15});//)
	{
	    return 0;
	}

	$$ref_imei=$1;

	while($line=~s/^(\d{2,10})?;//)
	{
	    $key_counter++;

	    if (defined $1)
	    {
		push (@$lref_keys, $1);
	    }
	    else
	    {
		push (@$lref_keys, "");
	    }
	} # while($line=~s/^(\d{2,10})?;/)
	#print "key_counter" .$key_counter;
	if (($key_counter!=6) && ($suffix_file eq "seed"))
	{
	    debug $h_ref_param, "Keys counter != 6. \n";
	    return 0;
	}

	if (($key_counter!=5) && ($suffix_file eq "D6"))
	{
	    debug $h_ref_param, "Keys counter != 5. \n";
	    return 0;
	}

	$$suffix = $suffix_file;

	#if ($imei_file != $imeicontent)
	if ($imei_file != $$ref_imei)
	{
	    close($fin); 
	    return 0;
        }

	close($fin);
	return 1;
    }
}

################################################################################
#
################################################################################
sub process
{
    my $h_ref_param=shift @_;
    my $err=0;
    my $total_processed_seed_file_counter=0;
    my $skipped_processed_seed_file_counter=0;
    my $error_processed_seed_file_counter=0;
    my $new_processed_seed_file_counter=0;

    my $imei="";
    my @lkeys=();
    my $suffix_file="";
   
    print_h_content($h_ref_param);
    
    if (! db_connect($h_ref_param))
    {
	error("Failed to connect to database.\n");
	return 1;
    }
    
    # Checking lock file existence first in order to avoid to run two same
    # instance of the tool in parallel.
    info "Checking lock file ... \n";
    if ( -f $h_ref_param->{LOCK_FILE})
    {
	info "Checking lock exits! Aborting ... \n";
	return 1;
    }
    
    info "Creating lock file ... \n";
    `touch $h_ref_param->{LOCK_FILE}`;
    if ($? != 0)
    {
	error("Failed to create lock file >$h_ref_param->{LOCK_FILE}< \n");
	return 1;
    }
    
    my @seedfilelist=();
    
    info "Listing SEED files in $G_SIMLOCKS_PATH/imported ...\n";
    
    @seedfilelist = get_seed_file_list($h_ref_param,"$G_SIMLOCKS_PATH/imported");
    
    if (scalar @seedfilelist == 0)
    {
	info "No SEED File Found.  \n";
	info "End of Process. \n";
    } 
    else 
    {
	
	info "Process files ... \n";
	
	foreach my $seedfile (@seedfilelist)
	{
	    $total_processed_seed_file_counter++;
	    chomp($seedfile);

	    my ($seedname,$seedpath,$seedsuffix) = fileparse("$seedfile",());
	    my $seed_create_date="";
	    my $mystat = stat($seedfile);
	    
	    debug $h_ref_param, "SEED file found: $seedname \n";

	    #print "Creation date: ".$mystat->ctime." ".get_date("/",localtime($mystat->ctime))." ".get_time(":",localtime($mystat->ctime))."\n";
	    $seed_create_date = get_date("-",localtime($mystat->mtime))." ".get_time(":",localtime($mystat->mtime));
	    #print "Creation date: $seed_create_date";
	    #exit 1;

	    if (! get_seed_content($h_ref_param,$seedfile,\$imei,\@lkeys,\$suffix_file))
	    {
		$error_processed_seed_file_counter++;
		error("SEED $seedname seems to be wrong. Skipping... \n");
		debug $h_ref_param, "File $seedname may be wrong. Will be moved to $G_SIMLOCKS_PATH/error \n";
		file_move($h_ref_param, "$seedfile", "$G_SIMLOCKS_PATH/error","SEED file '$seedfile'");
		next;

	    }

	    if (db_seed_file_already_processed($h_ref_param,substr($seedname,0,15)))
	    {
		debug $h_ref_param, "File $seedname already uploaded. Skipping ... \n";
		$skipped_processed_seed_file_counter++;
		file_move($h_ref_param, "$seedfile", "$G_SIMLOCKS_PATH/skipped","SEED file '$seedfile'");
		next;
	    } 

	    #if (! db_seed_insert_tmp($h_ref_param,\$imei,\@lkeys ))
	    
	    if (! db_seed_insert($h_ref_param,\$imei,\$suffix_file,$seed_create_date,\@lkeys))
	    {
		error("Couldn't upload file $seedname to DB. \n");
		$error_processed_seed_file_counter++;
		next;
	    }
	    
	    debug $h_ref_param, "lkeys: ".\@lkeys." -> ".join(",",@lkeys)."\n";
	    
	    $new_processed_seed_file_counter++; 
	    
	    debug $h_ref_param, "Removing file $seedname ... \n";
	    
	    if (! file_remove($h_ref_param, "$seedfile"))
	    {
		error("File $seedname couldn't be removed\n");
	    }
	    
	    debug $h_ref_param, "File $seedname removed. \n";
	    #sleep(3);

	} # foreach my $seedfile (@seedfilelist)
	
	info "End of Process. \n";

    } # if (scalar @seedfilelist == 0)
    
    info "Delete lock file ... \n";
    `rm -f $h_ref_param->{LOCK_FILE}`;
    
    info("### Summary: #################################################\n");
    info("Total SEED file Processed: $total_processed_seed_file_counter\n");
    info("         Included skipped: $skipped_processed_seed_file_counter\n");
    info("           Included error: $error_processed_seed_file_counter\n");
    info("             Included new: $new_processed_seed_file_counter\n");
    info("##################################\n");
    
    if (! db_disconnect($h_ref_param))
    {
	error("Failed to disconnect from database.\n");
	return 1;
    }
    
    return $err;
}

################################################################################
#
################################################################################
sub print_version
{
  my $h_ref_param=shift @_;
  print $h_ref_param->{EXECUTABLE_NAME}." ".$h_ref_param->{VERSION}." ".$h_ref_param->{RELEASE_DATE}."\n";
}

################################################################################
#
################################################################################
sub parse_args
{
    my $h_ref_param=shift @_;
    
    my $arg="";
    my $err=0;
    
    while ($arg=shift @ARGV)
    {
	chomp($arg);
	if ( $arg =~ /^-/ )
	{
	    if ( ($arg =~ /^-h/) || ($arg =~ /^--help/))
	    {
		print_usage($h_ref_param);
		exit(0);
	    }
	    elsif ( ($arg =~ /^-d/) || ($arg =~ /^--debug/))
	    {
		$h_ref_param->{DEBUG}=1;
	    }
	    elsif ( ($arg =~ /^-v/) || ($arg =~ /^--version/))
	    {
		print_version();
		exit(0);
	    }
	    
	    elsif ( ($arg =~ /^-l/) || ($arg =~ /^--log/))
	    {
		$arg=shift @ARGV;
		$h_ref_param->{LOG}=$arg;
	    }

	    else
	    {
		error "Unexpected option >$arg<.\n";
		$err++;
		next;
	    } 
	}
	else
	{
	    #<dbname>: Mandatory. Local database name to use to check for already downloaded archives.\n";
	    if (! exists $h_ref_param->{DBNAME})
	    {
		$h_ref_param->{DBNAME}=$arg;
	    }
	    #<dblogin>: Mandatory. Local database login to use <dbname> database.\n";
	    elsif (! exists $h_ref_param->{DBLOGIN})
	    {
		$h_ref_param->{DBLOGIN}=$arg;
	    }
	    #<dbpasswd>: Mandatory. Local database password to use <dbname> database.\n";
	    elsif (! exists $h_ref_param->{DBPASSWD})
	    {
		$h_ref_param->{DBPASSWD}=$arg;
	    }
	}
    }
    
    if (! exists $h_ref_param->{DBPASSWD})
    {
	error("Missing arguments.\n");
	$err++;
    }
    
    if ($err>0)
    {
	error "Aborting due to previous error(s). Use -h or --help for usage.\n";
	return 1;
    }
    
    return 0;
}
    
################################################################################
#
################################################################################
sub print_usage
  {
    my $h_ref_param=shift @_;

    print "USAGE: ".$h_ref_param->{EXECUTABLE_NAME}." [-h|--help] [-d|--debug] [-v|--version] [-l|--log <log file>] ...] <dbname> <dblogin> <dbpasswd> <archive passwd>\n";
    print "\n";
    print "PURPOSE:\n";
    print "   Upload the SEED files into the database \n";
    print "\n";
    print "PARAMETERS DESCRIPTION:\n";
    print "\n";
    print "   <dbname>: Mandatory. Local database name to use to check for already downloaded archives.\n";
    print "\n";
    print "   <dblogin>: Mandatory. Local database login to use <dbname> database.\n";
    print "\n";
    print "   <dbpasswd>: Mandatory. Local database password to use <dbname> database.\n";
    print "\n";
    print "OPTIONS DESCRIPTION:\n";
    print "   [-h|--help]:\n";
    print "      Print this usage message and exit.\n";
    print "\n";
    print "   [-v|--version]:\n";
    print "      Print the version number and exit.\n";
    print "\n";
    print "   [-d|--debug]:\n";
    print "      Print excessive output to understand the processing.\n";
    print "\n";
    print "\n";
  }

################################################################################
#
################################################################################
sub open_log
{
    my $h_ref_param=shift @_;

    if (! open($G_LOG,">>".$h_ref_param->{LOG}))
    {
	warning "Cannot create log file ".$h_ref_param->{LOG}." in current directory.\n";

	$h_ref_param->{LOG}="/tmp/".$h_ref_param->{EXECUTABLE_NAME}.".log";

	if (! open($G_LOG,">".$h_ref_param->{LOG}))
	{
	    warning "Still cannot create alternative log file ".$h_ref_param->{LOG}.". No log will be performed.\n";
	    $G_LOG=0;
	}
    }
}


################################################################################
#
################################################################################
sub intro
  {
    my $h_ref_param=shift @_;
    my $err=0;
    my $date_for_file="";

    # Updating some global variables.

    $h_ref_param->{START_TIME}=get_date("-")." ".get_time(":");

    $date_for_file=get_date("-")."_".get_time("-");
    
    $h_ref_param->{VERSION}="0.3.2";
    $h_ref_param->{EXECUTABLE_NAME}="import_seed.pl";

    $h_ref_param->{LOG}=$h_ref_param->{EXECUTABLE_NAME}.".$date_for_file.log";

    $h_ref_param->{LOCK_FILE}="/tmp/".$h_ref_param->{EXECUTABLE_NAME}.".lock";
    
    $h_ref_param->{RELEASE_DATE}="2007/10/12";

    # Following instruction forces flushing for each output to STDOUT or STDERR.
    $|=1;

    return 0;
  }

################################################################################
#
################################################################################
sub outtro
{
    my $h_ref_param=shift @_;
    if ($G_LOG)
    {
	close($G_LOG);
    }

    return 0;
}

################################################################################
#
################################################################################
sub main
{
  # This hash list will be used to store input parameters and some other
  # usefull information.
  # The actual valable keys are:
  #   VERSION:           string: current version of the tool.
  #   START_TIME:        string: start time of the script in the form YY_MM_DD.HH.MM.SS
  #   EXECUTABLE_NAME:   string: name of the current script.
  #   LOG:               string: name of the log file.
  #   RELEASE_DATE:      string: date of current tool release in form: YYYY/MM/DD
  #   DEBUG:             boolean: if this key exists, then the current script is run in
  #                               debug mode.
  #
  my %params=();
  
  if (intro(\%params)!=0)
  {
      error "Error while executing intro ... Aborting.\n";
      exit(1);
  }

  if (parse_args(\%params)!=0)
  {
      error "Error while parsing arguments ... Aborting.\n";
      exit(1);
  }
  
  open_log(\%params);

  if (process(\%params)!=0)
  {
      error "Error while processing ... Aborting.\n";
      exit(1);
  }

  if (outtro(\%params)!=0)
  {
      error "Error while executing outtro ... Aborting.\n";
      exit(1);
  }


}


################################################################################
#
################################################################################

main();
exit(0);

